package cn.ulc.socket.admin.service.deposit.impl;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.ulc.common.constant.PubDataConstant;
import cn.ulc.common.exception.PlatformException;
import cn.ulc.common.model.param.PaginationParam;
import cn.ulc.socket.admin.common.BaseService;
import cn.ulc.socket.admin.model.dto.member.WxUserListDTO;
import cn.ulc.socket.admin.model.param.deposit.BackBucketParam;
import cn.ulc.socket.admin.service.deposit.DepositServ;
import cn.ulc.socket.common.api.WxPayAPI;
import cn.ulc.store.dao.DepositDao;
import cn.ulc.store.dao.DepositOrderDao;
import cn.ulc.store.dao.DepositOrderItemDao;
import cn.ulc.store.dao.order.OrderDao;
import cn.ulc.store.dao.user.WeixinUserDao;
import cn.ulc.store.entity.Company;
import cn.ulc.store.entity.Deposit;
import cn.ulc.store.entity.DepositOrder;
import cn.ulc.store.entity.DepositOrderItem;
import cn.ulc.store.entity.order.Order;
import cn.ulc.store.entity.staff.Staff;
import cn.ulc.store.entity.user.WeixinUser;
import lombok.AllArgsConstructor;
import org.apache.commons.beanutils.converters.BigDecimalConverter;
import org.beetl.sql.core.engine.PageQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class DepositServImpl extends BaseService implements DepositServ {
    DepositDao depositDao;
    DepositOrderDao depositOrderDao;
    DepositOrderItemDao depositOrderItemDao;
    WeixinUserDao wxUserDao;
    OrderDao orderDao;
    WxPayAPI wxPayAPI;
    @Override
    public WxUserListDTO findDepositList(String key, PaginationParam param) {
        Staff loginUser = getCurrentUser();
        Map<String,Object> condition = new HashMap<>();
        condition.put("key",key);
        condition.put("companyId",loginUser.getCompanyId());
        PageQuery pageQuery = initPageQuery(param);
        pageQuery.setParas(condition);
        wxUserDao.findDepositListPage(pageQuery);
        List<WeixinUser> list = pageQuery.getList();
        if(list != null && list.size()>0){
            list.stream().forEach(t->{
                List<Deposit> depositList = t.getDeposit();
                t.setCount(t.getDeposit() != null?t.getDeposit().size():0l);
                t.setDepositTotal(BigDecimal.ZERO);
                if(depositList != null && depositList.size()>0){
                    depositList.stream().forEach(d->{
                        t.setDepositTotal(NumberUtil.add(t.getDepositTotal(),d.getAmount()));
                    });
                }
            });
        }
        return new WxUserListDTO(list,pageQuery.getTotalRow());
    }
    //生成唯一订单号
    public String generateCode() {
        Company company = getCurrentCompany();
        Calendar cal = Calendar.getInstance();
        String month = (cal.get(Calendar.MONTH)+1)> 10 ? (cal.get(Calendar.MONTH)+1)+"" : "0" +(cal.get(Calendar.MONTH)+1);
        String date = cal.get(Calendar.DATE)> 10 ? cal.get(Calendar.DATE)+"" : "0" +cal.get(Calendar.DATE);
        String idStr = company.getId().toString();
        if(idStr.length()<6){
            Integer len = 6-idStr.length();
            for(Integer i = 0;i<len;i++){
                idStr = "0"+idStr;
            }
        }
        String code = "R"+idStr+cal.get(Calendar.YEAR)+month+date;
        String maxOrderNo = depositOrderDao.findMaxOrderNo(code);
        String orderNo = "0001";
        if (maxOrderNo != null) {
            orderNo = Integer.valueOf(maxOrderNo.substring(15))+1+"";
            Integer zeroLen = 4-orderNo.length();
            for(Integer i = 0;i<zeroLen;i++){
                orderNo = "0"+orderNo;
            }
        }
        return code+orderNo;
    }

    @Override
    @Transactional
    public Boolean backBucket(BackBucketParam param) {
        Long[] ids = new Long[param.getDeposits().size()];
        List<Deposit> depositList = depositDao.findBatch(param.getDeposits().toArray(ids));
        if(depositList != null && depositList.size()>0){
            List<String> orders = new ArrayList<>();
            Map<String,List<Deposit>> map = depositList.stream().collect(Collectors.groupingBy(Deposit::getOrderNo));
            // TODO 多个订单需要多个退单,操作失误机滤较大,不好处理
            if(map.entrySet().size()>1) throw new PlatformException("请选择同一订单操作");
//            for (Map.Entry<String, List<Deposit>> entry : map.entrySet()) {
//                orders.add( createOrder(entry.getKey(), entry.getValue()) );
//            }

            String refundNo = createOrder(depositList.get(0).getOrderNo(),depositList);
            Map<String,Object> result = wxPayAPI.depositRefund(refundNo);
            if(Boolean.valueOf(result.get("success").toString()) == false){
                throw new PlatformException(result.get("msg").toString());
            }
            return true;
        }
        return false;
    }

    public String createOrder(String tradeNo,List<Deposit> depositList){
        Order tradeOrder = orderDao.findByOrderNo(tradeNo);
        if(tradeOrder == null) throw new PlatformException("未获取到桶押金信息");
        Deposit deposit = depositList.get(0);
        DepositOrder order = new DepositOrder();
        setBaseInfo(order);
        order.setTradeNo(tradeOrder.getOrderNo());
        order.setTransactionId(tradeOrder.getTransactionId());
        order.setOrderNo(generateCode());
        order.setStatus(PubDataConstant.ORDER_UNPAID);
        order.setWxUserId(deposit.getWxUserId());
        order.setMemberId(deposit.getMemberId());
        order.setCount(new BigDecimal(depositList.size()));
        order.setPayAmount(BigDecimal.ZERO);
        depositOrderDao.save(order);
        List<DepositOrderItem> itemList = new ArrayList<>();
        depositList.stream().forEach(d -> {
            DepositOrderItem item = new DepositOrderItem();
            setBaseInfo(item);
            item.setOrderId(order.getId());
            item.setWxUserId(order.getWxUserId());
            item.setMemberId(order.getMemberId());
            item.setDepositId(d.getId());
            item.setPrice(d.getAmount());
            item.setNum(BigDecimal.ONE);
            item.setAmount(d.getAmount());
            item.setRemark("桶押金");
            itemList.add(item);
            order.setPayAmount(NumberUtil.add(order.getPayAmount(), item.getAmount()));
        });
        depositOrderDao.save(order);
        depositOrderItemDao.saveAll(itemList);
        return order.getOrderNo();
    }
}
